<template>
  <div>
    <el-upload
      :action="uploadUrl"
      :data="null"
      :headers="headers"
      :file-list="fileList"
      :before-upload="beforeUpload"
      :on-remove="handleRemove"
      :on-success="handleUploadSuccess"
      :on-preview="handlePreview"
      :limit="maxCount"
      :on-exceed="handleExceed"
      :accept="accept"
      :list-type="listType"
      :multiple="multiple"
    >
      <slot>
        <i v-if="listType === 'picture-card'" class="el-icon-plus"></i>
        <el-button v-else size="small" type="primary">上传文件</el-button>
      </slot>
      <!-- 添加 tip 插槽 -->
      <div v-if="$slots.tip">
        <slot name="tip"></slot>
      </div>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible">
      <template v-if="isImage(dialogImageUrl)">
        <img width="100%" :src="dialogImageUrl" alt="Preview" />
      </template>
      <template v-else>
        <p>无法预览文件</p>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import store from "@/store";
import { getToken } from "@/utils/auth";
import { downloadFile } from "@/utils/file";

export default {
  name: "FileUpload",
  props: {
    value: {
      type: Array | String,
      // default: () => [],
    },
    maxCount: {
      type: Number,
      default: 5,
    },
    accept: {
      type: String,
      default: "*", // 允许任何文件
    },
    listType: {
      type: String,
      default: "text",
      validator: (value) => {
        return ["text", "picture", "picture-card"].includes(value);
      },
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    // valueType: {
    //   type: String,
    //   default: "url",
    // },
    valueType: {
      type: String,
      default: "item", // url-array: 链接数组， item: 仅字符串， obj-array：{name, url}数组
    },
  },
  data() {
    return {
      dataObj: {
        policy: "",
        signature: "",
        key: "",
        ossaccessKeyId: "",
        dir: "",
        host: "",
      },
      dialogVisible: false,
      dialogImageUrl: null,
      uploadUrl: `${process.env.BASE_API}oss/upload`,
    };
  },
  computed: {
    fileList() {
      if (!this.value) {
        return [];
      }

      let files = this.value;
      if (this.valueType === "item") {
        files = [this.value];
      }

      return files.map((item) => ({
        name: this.valueType === "obj-array" ? item.name : item,
        url: this.valueType === "obj-array" ? item.url : item,
      }));
    },
    headers() {
      return store.getters.token
        ? {
            Authorization: getToken(), // 携带 token
          }
        : {};
    },
  },

  methods: {
    emitInput(fileList) {
      const urls = fileList.map((file) => {
        if (this.valueType === "obj-array") {
          return {
            name: file.name,
            url: file.url,
          };
        } else {
          return file.url;
        }
      });

      this.$emit(
        "input",
        this.valueType === "obj-array" || this.valueType === "url-array"
          ? urls
          : urls.join(""),
      );
    },
    handleRemove(file, fileList) {
      this.emitInput(fileList);
    },
    handlePreview(file) {
      if (this.accept.indexOf("image/") > -1) {
        this.dialogVisible = true;
        this.dialogImageUrl = file.url;
      } else {
        // downloadFile(file.url);
        // 在新的tab页面打开文件
        window.open(file.url, "_blank");
      }
    },
    beforeUpload(file) {
      return true;
    },
    handleUploadSuccess(res, file) {
      let url = res.data;
      if (!this.multiple) {
        this.emitInput([
          {
            url: res.data,
            name: res.data,
          },
        ]);
      } else {
        this.emitInput([...this.fileList, { name: file.name, url }]);
      }
    },
    handleExceed() {
      this.$message({
        message: `最多只能上传 ${this.maxCount} 个文件`,
        type: "warning",
      });
    },
    isImage(fileUrl) {
      if (!fileUrl) return false;
      const urlWithoutQuery = fileUrl.split("?")[0]; // 去除 URL 中的查询参数
      return /\.(jpeg|jpg|png|gif|bmp|svg|webp)$/i.test(urlWithoutQuery);
    },
  },
};
</script>

<style scoped></style>
